﻿using Castle.DynamicProxy;
using Facebook.Core;
using Facebook.Core.Contracts;
using Facebook.Core.Responses;
using Facebook.Core.Services;

namespace Facebook.Fluent
{
    public class FB
    {
        private static readonly FacebookConfiguration configuration = new FacebookConfiguration();

        public static WithFluentInterface For(string apiKey, string secret)
        {
            configuration.ApiKey = apiKey;
            configuration.Secret = secret;

            return new WithFluentInterface(configuration);
        }
    }

    public class FacebookConfiguration
    {
        public string ApiKey { get; set; }

        public string Secret { get; set; }

        public IFacebookSessionManager SessionManager { get; set; }

        public IAuthenticationHandler AuthenticationHandler { get; set; }
    }

    public class WithFluentInterface
    {
        public WithFluentInterface(FacebookConfiguration configuration)
        {
            Configuration = configuration;
        }

        private FacebookConfiguration Configuration { get; set; }

        public BuildFluentInterface WithDefaultSessionManager(IAuthenticationHandler authenticationHandler)
        {
            Configuration.SessionManager = new DefaultSessionManager();
            Configuration.AuthenticationHandler = authenticationHandler;
            return new BuildFluentInterface(Configuration);
        }

        public BuildFluentInterface With(IFacebookSessionManager sessionManager)
        {
            Configuration.SessionManager = sessionManager;

            return new BuildFluentInterface(Configuration);
        }

    }

    public interface IAuthenticationHandler
    {
        void AuthenticateUser(string uri);
    }

    internal class DefaultSessionManager : IFacebookSessionManager
    {
        #region Implementation of IFacebookSessionManager

        public string GetSession()
        {
            return SessionKey;
        }

        public void SetSession(string sessionKey)
        {
            SessionKey = sessionKey;
        }

        private string SessionKey { get; set; }

        #endregion
    }

    public class BuildFluentInterface
    {
        public BuildFluentInterface(FacebookConfiguration configuration)
        {
            Configuration = configuration;
        }

        private FacebookConfiguration Configuration { get; set; }

        public IFacebookService Build
        {
            get
            {
                var proxyGenerator = new ProxyGenerator();

                var facebookService = proxyGenerator.CreateClassProxy<FacebookService>(
                    new ApiCallInterceptor(
                        Configuration.ApiKey,
                        Configuration.Secret,
                        Configuration.SessionManager
                        ));

                if(Configuration.SessionManager.GetType() == typeof(DefaultSessionManager))
                {
                    auth_createToken_response_wrapper token = facebookService.createToken();

                    Configuration.AuthenticationHandler.AuthenticateUser(
                        string.Format(
                        "https://login.facebook.com/login.php?api_key={0}&auth_token={1}&v={2}&popup", 
                        Configuration.ApiKey,
                        token.auth_createToken_response,
                        "1.0"));

                    auth_getSession_response session = facebookService.getSession(token.auth_createToken_response);
                    Configuration.SessionManager.SetSession(session.session_key);
                }
                
                return facebookService;
            }
        }
    }
}